/**
 * Trabajo de Ingeniería de Software 2
 * Año 2008
 * Sistema de Reserva de Recursos.
 * Desarrolladores: - Marcelo Ferreira.
 *                  - Christian Gómez.
 *                  - Marcelo Rodas.
 */
package reportes;

import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.*;
import javax.servlet.http.*;
import net.sf.jasperreports.view.JasperViewer;
import java.io.*;
import java.sql.ResultSet;
import java.sql.Statement;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.export.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import net.sf.jasperreports.engine.JasperRunManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import modelo.Usuario;

/**
 * Clase servletReportes
 * Esta clase se encarga de manejar todas las peticiones de reportes
 * y desplegarlas en pantalla o exportarlas a pdf y rtf dependiendo
 * de los parametros recibidos como entrada
 * @author jmferreira
 */
public class servletReportes extends HttpServlet {

    private static final Log log = LogFactory.getLog(servletReportes.class);

    /** 
     * Procesa las peticiones de los metodos HTTP <code>GET</code> y <code>POST</code>.
     * @param request Peticion servlet 
     * @param response Respuesta servlet
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        //Obtiene el usuario de la sesion
        HttpSession session = request.getSession(true);
        Usuario usuarioLogeado = (Usuario) session.getAttribute("user");
        //Formateador de fechas
        DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
        String reportSource;
        //Obtener los parametros del reporte
        String fdesde = request.getParameter("fechadesde");
        String fhasta = request.getParameter("fechahasta");
        String tipoReporte = request.getParameter("tiporeporte");
        String nombreReporte = request.getParameter("nombrereporte");
        String tipoRecurso = request.getParameter("idtiporecurso");
        String recurso = request.getParameter("idrecurso");
//        if (recurso.equals("")){
//            recurso="%";
//        }
        //Realiza el mapeo de los parametros recibidos del reporte para enviarlo al XML
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("author", usuarioLogeado.getIddatospersonales().getApellidos() + ", " + usuarioLogeado.getIddatospersonales().getNombres());
        params.put("tiporecurso", tipoRecurso);
        params.put("recurso", recurso);

        try {
            params.put("fdesde", dateFormat.parse(fdesde));
            params.put("fhasta", dateFormat.parse(fhasta));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            // Disponibiliza la clase driver
            Class.forName("org.postgresql.Driver");

            // Crea una conexion para pasarlo al reporte.
            java.sql.Connection conn = DriverManager.getConnection(
                    "jdbc:postgresql://localhost:5432/srr", "postgres", "postgres");

            if (nombreReporte.equals("rptCalendarioReservaRecurso")) {
                Statement statement = conn.createStatement();
                String query = "SELECT f_generar_calendario('" + fdesde + "','" + fhasta + "','" + recurso + "') ";
                // Perform the query              
                ResultSet rs = statement.executeQuery(query);
            }
            //Seleccion de los destinos de reportes (vista, pdf, rtf)
            if (tipoReporte.equals("VPREVIA")) { //VISTA PREVIA

                reportSource = this.obtenerPlantillaXML(nombreReporte);
                JasperReport jasperReport = JasperCompileManager.compileReport(reportSource);
                this.generateViewer(response, params, jasperReport, conn);

            } else if (tipoReporte.equals("PDF")) { //PDF

                reportSource = this.obtenerPlantillaXML(nombreReporte);
                JasperReport jasperReport = JasperCompileManager.compileReport(reportSource);
                this.generatePDFOutput(response, params, jasperReport, conn);

            } else if (tipoReporte.equals("XLS")){ //XLS
                reportSource = this.obtenerPlantillaXML(nombreReporte);
                JasperReport jasperReport = JasperCompileManager.compileReport(reportSource);
                this.generateXLSOutput(response, params, jasperReport, conn);
            }else{ //HTML
                reportSource = this.obtenerPlantillaXML(nombreReporte);
                JasperReport jasperReport = JasperCompileManager.compileReport(reportSource);
                this.generateHTMLOutput(response, params, jasperReport, conn);
                
            }

        } catch (JRException e) {
            e.printStackTrace();
        } // Manejo de Excepciones para el metodo Class.forName.
        catch (ClassNotFoundException ex) {
            ex.printStackTrace();

        } // Manejo de Excepciones para el metodo DriverManager.getConnection.
        catch (SQLException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Genera el reporte en vista preliminar conforme a los parametros recibidos
     * @param response
     * @param parameters
     * @param jasperReport
     * @param conn
     * @throws net.sf.jasperreports.engine.JRException
     * @throws java.sql.SQLException
     * @throws java.io.IOException
     */
    private void generateViewer(
            HttpServletResponse response,
            Map parameters,
            JasperReport jasperReport, java.sql.Connection conn) throws JRException, SQLException, IOException {
        PrintWriter out = response.getWriter();
        //Realiza el llenado de los datos
        JasperPrint jasperPrint =
                JasperFillManager.fillReport(
                jasperReport,
                parameters,
                conn);

        JasperViewer.viewReport(jasperPrint, false);
        out.println("REPORTE GENERADO EXITOSAMENTE");
    }

    /**
     * Exporta el reporte en XLS conforme a los parametros recibidos 
     * @param response
     * @param parameters
     * @param jasperReport
     * @param conn
     * @throws net.sf.jasperreports.engine.JRException
     * @throws java.sql.SQLException
     * @throws java.io.IOException
     */
    private void generateXLSOutput(
            HttpServletResponse response,
            Map parameters,
            JasperReport jasperReport, java.sql.Connection conn) throws JRException, SQLException, IOException {
        int bit;
        File f;
        InputStream in;
        ServletOutputStream output;
//Realiza el llenado de los datos        
        JasperPrint jasperPrint =
                JasperFillManager.fillReport(
                jasperReport,
                parameters,
                conn);

        String xlsFileName = "Reporte.xls";
        //Creacion del XLS
        JRXlsExporter exporter = new JRXlsExporter();
        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
        exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, xlsFileName);
        exporter.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.TRUE);
        exporter.exportReport();

        // En este punto ya esta Creado el XLS
        // Ahora leemos el fichero y forzamos al navegador a que nos descargue el fichero.
        f = new File(xlsFileName);

        response.setContentType("application/vnd.ms-excel"); //Tipo de fichero.

        response.setHeader("Content-Disposition", "attachment;filename=\"" + xlsFileName + "\""); //Configurar cabecera http

        in = new FileInputStream(f);
        output = response.getOutputStream();

        bit = 256;
        while ((bit) >= 0) {
            bit = in.read();
            output.write(bit);
        }

        output.flush();
        output.close();
        in.close();
    }

    /**
     * Exporta el reporte en PDF conforme a los parametros recibidos
     * @param response
     * @param parameters
     * @param jasperReport
     * @param conn
     * @throws net.sf.jasperreports.engine.JRException
     * @throws java.sql.SQLException
     * @throws java.io.IOException
     */
    private void generatePDFOutput(
            HttpServletResponse response,
            Map parameters,
            JasperReport jasperReport, java.sql.Connection conn) throws JRException, SQLException, IOException {
        ServletOutputStream output;
        byte[] fichero = JasperRunManager.runReportToPdf(jasperReport, parameters, conn);
// Y enviamos el pdf a la salida del navegador como podríamos hacer con cualquier otro pdf
        response.setContentType("application/pdf");
        response.setHeader("Content-disposition", "inline; filename=informeDemo.pdf");
        response.setHeader("Cache-Control", "max-age=30");
        response.setHeader("Pragma", "No-cache");
        response.setDateHeader("Expires", 0);
        response.setContentLength(fichero.length);
        output = response.getOutputStream();
        output.write(fichero, 0, fichero.length);
        output.flush();
        output.close();
    }

    private void generateHTMLOutput(
            HttpServletResponse response,
            Map parameters,
            JasperReport jasperReport, java.sql.Connection conn) throws JRException, SQLException, IOException {
        JRExporter exporter = null;
        exporter = new JRHtmlExporter();
        PrintWriter printWriter = response.getWriter();
//        request.getSession().setAttribute(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint);
//Realiza el llenado de los datos        
        JasperPrint jasperPrint =
                JasperFillManager.fillReport(
                jasperReport,
                parameters,
                conn);

        /* printWriter here is a reference for  response.getWriter() */
        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
        exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, printWriter);


        // gonna set url pattern given for Image servlet with a reponse parameter <url-pattern>/imageServlet</url-pattern>  
        exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, "imageServlet?image=");

        response.setContentType("text/html");

        /* Would write the HTML content to ServletStream Provided */
        exporter.exportReport();
    }

    /**
     * Obtiene la plantilla que sera utilizada para la generación del reporte
     * @param nombreReporte
     * @return
     */
    private String obtenerPlantillaXML(String nombreReporte) {
        String reportSource; //El XML del template del reporte

        ServletContext context = this.getServletConfig().getServletContext();

        if (nombreReporte.equals("rptAuditoriaAcceso")) {
            reportSource = context.getRealPath("report/templates/AuditoriaAcceso.jrxml");

        } else if (nombreReporte.equals("rptSolicitudReservaGeneral")) {
            reportSource = context.getRealPath("report/templates/SolicitudReservaGeneral.jrxml");
        } else if (nombreReporte.equals("rptSolicitudReservaPorRecurso")) {
            reportSource = context.getRealPath("report/templates/SolicitudReservaPorRecurso.jrxml");
        } else if (nombreReporte.equals("rptEstadisticaSolicitudReserva")) {
            reportSource = context.getRealPath("report/templates/EstadisticaSolicitudReservaRecursos.jrxml");
        } else if (nombreReporte.equals("rptAuditoriaSolicitudReserva")) {
            reportSource = context.getRealPath("report/templates/AuditoriaSolicitudReserva.jrxml");
        } else if (nombreReporte.equals("rptMovimientoRecurso")) {
            reportSource = context.getRealPath("report/templates/MovimientoRecurso.jrxml");
        } else if (nombreReporte.equals("rptAuditoriaSolicitudUsuario")) {
            reportSource = context.getRealPath("report/templates/AuditoriaSolicitudUsuario.jrxml");
        } else if (nombreReporte.equals("rptCalendarioReservaRecurso")) {
            reportSource = context.getRealPath("report/templates/CalendarioRecurso.jrxml");
        } else if (nombreReporte.equals("rptAuditoriaDatosPersonales")) {
            reportSource = context.getRealPath("report/templates/AuditoriaDatosPersonales.jrxml");            
        } else if (nombreReporte.equals("rptAuditoriaUsuario")) {
            reportSource = context.getRealPath("report/templates/AuditoriaUsuario.jrxml");
        } else if (nombreReporte.equals("rptAuditoriaReserva")) {
            reportSource = context.getRealPath("report/templates/AuditoriaReserva.jrxml");
        } else {
            reportSource = context.getRealPath("report/templates/AuditoriaAcceso.jrxml");
        }
        return reportSource;
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     */
    public String getServletInfo() {
        return "Short description";
    }
    // </editor-fold>
}
